<template>
  <div id="map" class="map-container"></div>
</template>

<script lang="ts">
import { defineComponent, onMounted, onUnmounted } from 'vue';
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import ImageTile from 'ol/source/ImageTile'; // 导入 ImageTile 用于高德地图
import VectorSource from 'ol/source/Vector';
import VectorLayer from 'ol/layer/Vector';
import Feature from 'ol/Feature';
import Point from 'ol/geom/Point';
import { fromLonLat } from 'ol/proj';
import Style from 'ol/style/Style';
import Icon from 'ol/style/Icon';
import Modify from 'ol/interaction/Modify';
import Collection from 'ol/Collection';
import { defaults as defaultControls } from 'ol/control'; // 导入 defaultControls，用于禁用默认控件

export default defineComponent({
  name: 'DraggableIconMap',
  setup() {
    let map: Map | null = null;
    let modifyInteraction: Modify | null = null;

    onMounted(() => {
      // 1. 创建高德地图卫星图层
      const gaodeSatelliteLayer = new TileLayer({
        source: new ImageTile({
          url: 'https://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
        }),
        properties: {
          name: '高德卫星图',
        },
      });

      // 2. 创建高德地图路网图层 (可以叠加在卫星图之上)
      const gaodeRoadLayer = new TileLayer({
        source: new ImageTile({
          url: 'https://webst0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8',
        }),
        properties: {
          name: '高德路网图',
        },
      });

      // 3. 创建一个用于放置可拖拽图标的矢量源
      // 矢量源存储地理空间数据，例如点、线、面。这里明确指定存储 Point 几何类型的特征。
      const vectorSource = new VectorSource<Point>({
        features: [], // 初始时没有特征，我们将在下面添加
      });

      // 4. 创建一个矢量层来渲染矢量源中的特征
      const vectorLayer = new VectorLayer({
        source: vectorSource,
        properties: {
          name: '可拖拽图标层',
        },
      });

      // 5. 定义图标的样式
      // 这里我们使用 public 目录下的 vite.svg 作为图标
      // 注意：路径 '/vite.svg' 是相对于 public 目录的根路径
      const iconStyle = new Style({
        image: new Icon({
          anchor: [0.5, 1], // 图标锚点：[0.5, 1] 表示图标的中心点在 X 轴上，底部在 Y 轴上。
          anchorXUnits: 'fraction', // X 轴锚点单位是分数 (0-1)，0.5 代表中心
          anchorYUnits: 'fraction', // Y 轴锚点单位是分数 (0-1)，1 代表底部
          src: '/vite.svg', // 图标图片的路径。请确保 public 目录下有 vite.svg 文件。
          scale: 0.5, // **将图标缩放比例增大到 0.5 (原始大小的 50%)，以确保其可见。**
          // 如果图标仍然太小，可以尝试更大的值，例如 1 (原始大小)。
        }),
      });

      // 6. 创建一个点特征 (Feature) 并明确其几何类型为 Point
      // 特征是地理空间数据（如点、线、面）的抽象表示。
      // 我们将图标放置在上海的经纬度坐标。
      const iconFeature: Feature<Point> = new Feature({
        geometry: new Point(fromLonLat([121.473701, 31.230416])), // 使用 OpenLayers 的 fromLonLat 转换坐标，确保坐标系正确。
        name: '可拖拽图标', // 可以给特征一个名称，用于识别。
      });

      // 7. 将样式应用到点特征
      iconFeature.setStyle(iconStyle);

      // 8. 将图标特征添加到矢量源中
      vectorSource.addFeature(iconFeature);

      // 9. 初始化 OpenLayers 地图
      map = new Map({
        target: 'map', // 地图将渲染到 id 为 'map' 的 div 元素中。确保 HTML 模板中存在 id 为 'map' 的 div。
        layers: [
          gaodeSatelliteLayer, // 添加高德卫星图层作为底图
          gaodeRoadLayer,      // 添加高德路网图层叠加在卫星图之上
          vectorLayer,         // 添加包含可拖拽图标的矢量层
        ],
        view: new View({
          center: fromLonLat([121.473701, 31.230416]), // 设置地图中心点为图标的初始位置。
          zoom: 12, // 初始缩放级别。
        }),
        // 10. 禁用所有默认控件
        // 通过设置 controls 为 defaultControls() 的空扩展，可以移除缩放、旋转、版权信息等默认控件。
        controls: defaultControls({
          zoom: false,        // 禁用缩放按钮
          rotate: false,      // 禁用旋转按钮
          attribution: false, // 禁用版权信息
        }).extend([]), // 确保没有其他默认控件被添加到地图上
      });

      // 11. 创建 Modify 交互
      // Modify 交互允许用户通过拖拽来修改现有特征的几何形状。
      // 这里我们使用它来拖拽图标（图标是一个点特征，拖拽就是修改点的坐标）。
      // Collection 用于存储所有可以被 Modify 交互操作的特征。这里我们只放入 iconFeature。
      const featuresToModify = new Collection<Feature<Point>>([iconFeature]);
      modifyInteraction = new Modify({
        features: featuresToModify, // 指定要修改的特征集合
      });

      // 12. 将 Modify 交互添加到地图中
      // 添加交互后，用户就可以通过鼠标拖拽图标了。
      map.addInteraction(modifyInteraction);

      // 13. 可选：监听特征修改事件 (例如，当拖拽结束时)
      // 这个事件会在用户完成拖拽（即释放鼠标）时触发。
      modifyInteraction.on('modifyend', function (event) {
        // 获取被修改的特征的几何对象。我们断言其类型为 Point，以便调用 getCoordinates() 方法。
        const modifiedGeometry = event.features.getArray()[0].getGeometry() as Point;
        console.log('图标被拖拽并修改，新坐标为:', modifiedGeometry.getCoordinates());
        // 可以将新的坐标发送到后端，或者更新 Vue 组件的状态等。
      });
    });

    onUnmounted(() => {
      if (map) {
        if (modifyInteraction) {
          map.removeInteraction(modifyInteraction);
          modifyInteraction = null;
        }
        map.setTarget(undefined);
        map = null;
      }
    });

    return {}; // setup 函数需要返回一个对象，即使是空的。
  },
});
</script>

<style scoped>
/* 定义地图容器的样式 */
.map-container {
  width: 100%;
  height: 600px; /* 设置地图容器的高度，确保地图有足够的空间显示 */
  background-color: #f0f0f0; /* 可选：设置背景色以便于查看地图区域 */
}
</style> 